package com.javacoo.xservice.base.filter.csrf;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;

import com.javacoo.xservice.base.Constants;
import com.javacoo.xservice.base.utils.WebUtil;

import lombok.extern.slf4j.Slf4j;

/**
 * Csrf过滤器
 * <p>说明:</p>
 * <li>跨站请求伪造攻击过滤器</li>
 * @author: duanyong@jccfc.com
 * @since: 2021/3/17 14:20
 */
@Slf4j
public class CsrfFilter implements Filter {
    private List<String> excludes = new ArrayList<>();

    private boolean enabled = false;
	@Override
	public void init(FilterConfig filterConfig) {
        String strExcludes = filterConfig.getInitParameter("excludes");
        String strEnabled = filterConfig.getInitParameter("enabled");
        //将不需要xss过滤的接口添加到列表中
        if(StringUtils.isNotEmpty(strExcludes)){
            String[] urls = strExcludes.split(",");
            for(String url:urls){
                excludes.add(url);
            }
        }
        if(StringUtils.isNotEmpty(strEnabled)){
            enabled = Boolean.valueOf(strEnabled);
        }
	}
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		try {
			HttpServletRequest req = (HttpServletRequest) request;
			HttpServletResponse res = (HttpServletResponse) response;
			// 获取请求url地址
			String url = req.getRequestURL().toString();
			String referurl = req.getHeader("Referer");
			if (isWhiteReq(referurl)) {
				chain.doFilter(request, response);
			} else {
				req.getRequestDispatcher("/").forward(req, res);
				// 记录跨站请求日志
				String logstr = "";
				String date = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
				String clientIp = WebUtil.getHost(req);

                logstr = clientIp + "||" + date + "||" + referurl + "||" + url;
				log.warn(logstr);
				return;
			}
		} catch (Exception e) {
            log.error("doFilter", e);
		}
	}

	/**
	 * 判断是否是白名单
	 * <p>说明:</p>
	 * <li></li>
	 * @param referUrl
	 * @return
	 * @since 2017年2月10日上午8:55:03
	 */
	private boolean isWhiteReq(String referUrl) {
        if(!enabled){
            //如果开关关闭了，则所有url都不拦截
            return true;
        }
		if (StringUtils.isBlank(referUrl)) {
			return true;
		} else {
			String refHost = "";
			referUrl = referUrl.toLowerCase();
			if (referUrl.startsWith(Constants.HTTP)) {
				refHost = referUrl.substring(7);
			} else if (referUrl.startsWith(Constants.HTTPS)) {
				refHost = referUrl.substring(8);
			}

			for (String urlTemp : excludes) {
				if (refHost.indexOf(urlTemp.toLowerCase()) > -1) {
					return true;
				}
			}
		}
		return false;
	}
	@Override
	public void destroy() {
	}

}
